package com.base.vistter.iframe.service;

import com.base.vistter.iframe.constant.FileConstant;
import com.base.vistter.iframe.entity.SysAttachment;
import com.base.vistter.iframe.entity.SysProject;
import com.base.vistter.iframe.exception.IframeException;
import com.base.vistter.iframe.mapper.SysAttachmentMapper;
import com.base.vistter.iframe.properties.MinioProperties;
import com.base.vistter.iframe.template.MinioTemplate;
import com.base.vistter.iframe.utils.UploadUtils;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.io.InputStream;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Objects;
import java.util.regex.Pattern;

@Service
@Transactional
@Slf4j
public class SysAttachmentService extends BaseService<SysAttachmentMapper, SysAttachment>{

    private static final DateFormat dateFormat = new SimpleDateFormat("yyyyMMddHH");

    private static final Pattern IMAGE_FILE_PATTERN = Pattern.compile(".*\\.(jpg|jpeg|png|gif|bmp)$", Pattern.CASE_INSENSITIVE);

    @Resource(name = "minioTemplate")
    private MinioTemplate minioTemplate;
    @Resource(name = "minioProperties")
    private MinioProperties minioProperties;
    @Resource(name = "sysProjectService")
    private SysProjectService sysProjectService;

    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = IframeException.class)
    public String saveSysAttachment(MultipartFile multipartFile, boolean watermark) throws IframeException {
        InputStream inputStream = null;
        BufferedImage bufferedImage = null;
        InputStream is = null;
        try {
            String filePath = dateFormat.format(new Date()) + UploadUtils.getRandom() + FileConstant.SPRIT + multipartFile.getOriginalFilename();
            SysAttachment sysAttachment = new SysAttachment();
            sysAttachment.setName(multipartFile.getOriginalFilename());
            sysAttachment.setBucketName(minioProperties.getBucketName());
            sysAttachment.setFileSize(multipartFile.getSize());
            sysAttachment.setFileType(multipartFile.getContentType());
            sysAttachment.setFilePath(minioProperties.getBucketName() + FileConstant.SPRIT + filePath);
            super.save(sysAttachment);
            inputStream = multipartFile.getInputStream();
            if (watermark && Objects.requireNonNull(multipartFile.getContentType()).startsWith("image/") && IMAGE_FILE_PATTERN.matcher(multipartFile.getOriginalFilename()).matches()) {
                bufferedImage = this.addWaterMark(inputStream);
                is = UploadUtils.bufferedImageToInputStream(bufferedImage, UploadUtils.getFileExt(multipartFile.getOriginalFilename()));
                minioTemplate.uploadFile(minioProperties.getBucketName(), filePath, is);
            } else {
                minioTemplate.uploadFile(minioProperties.getBucketName(), filePath, inputStream);
            }
            return sysAttachment.getFilePath();
        } catch (Exception e) {
            throw new IframeException(e.getMessage());
        } finally {
            try {
                if (inputStream != null) {
                    inputStream.close();
                }
                if (is != null) {
                    is.close();
                }
            } catch (IOException e) {
                log.error(e.getMessage());
            }
        }
    }

    private BufferedImage addWaterMark(InputStream inputStream) throws IframeException {
        SysProject sysProject = sysProjectService.selectOne();
        InputStream iconInputStream = null;
        BufferedImage bufferedImage = null;
        try {
            iconInputStream = minioTemplate.downloadFile(sysProject.getIcon());
            bufferedImage = ImageIO.read(inputStream);
            BufferedImage iconBufferedImage = ImageIO.read(iconInputStream);
            if (bufferedImage.getWidth() >= iconBufferedImage.getWidth() || bufferedImage.getHeight() >= iconBufferedImage.getHeight()) {
                Graphics2D g = bufferedImage.createGraphics();
                g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, 0.8f));
                g.drawImage(iconBufferedImage, bufferedImage.getWidth() - iconBufferedImage.getWidth(), bufferedImage.getHeight() - iconBufferedImage.getHeight(), null);
                g.dispose();
            }
        } catch (IOException e) {
            log.error(e.getMessage());
        } finally {
            try {
                if (iconInputStream != null) {
                    iconInputStream.close();
                }
            } catch (IOException e) {
                log.error(e.getMessage());
            }
        }
        return bufferedImage;
    }

}
